package com.xinqi.modules.sys.complaint.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xinqi.common.base.enums.YesNoNumberEnum;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.base.response.PageInfo;
import com.xinqi.common.base.response.Param;
import com.xinqi.common.base.response.R;
import com.xinqi.common.core.constant.ChatRemindConstants;
import com.xinqi.common.core.enums.ChatRemindTypeEnum;
import com.xinqi.common.core.enums.ComplaintConfigDisableFeatureEnum;
import com.xinqi.common.core.enums.UserStatusEnum;
import com.xinqi.common.core.utils.DateUtils;
import com.xinqi.common.core.utils.MessageUtils;
import com.xinqi.common.core.utils.PlaceholderUtils;
import com.xinqi.common.core.utils.StringUtils;
import com.xinqi.common.mybatis.utils.Pages;
import com.xinqi.modules.chat.chat.official.client.ChatRemindContentClient;
import com.xinqi.modules.chat.chat.official.dto.req.ChatRemindContentBatchCreateDTO;
import com.xinqi.modules.chat.chat.official.dto.req.ChatRemindContentCreateDTO;
import com.xinqi.modules.chat.chat.rongyun.RemoteRongyunClient;
import com.xinqi.modules.sys.complaint.convert.ComplaintConvert;
import com.xinqi.modules.sys.complaint.domain.ComplaintConfigEntity;
import com.xinqi.modules.sys.complaint.domain.ComplaintEntity;
import com.xinqi.modules.sys.complaint.dto.req.AccountUnblockingQueryDTO;
import com.xinqi.modules.sys.complaint.dto.req.ComplaintCreateDTO;
import com.xinqi.modules.sys.complaint.dto.req.ComplaintDeleteDTO;
import com.xinqi.modules.sys.complaint.dto.req.ComplaintHandlingDTO;
import com.xinqi.modules.sys.complaint.dto.req.ComplaintQueryDTO;
import com.xinqi.modules.sys.complaint.dto.rsp.ComplaintResultDTO;
import com.xinqi.modules.sys.complaint.manager.ComplaintConfigManager;
import com.xinqi.modules.sys.complaint.manager.ComplaintManager;
import com.xinqi.modules.sys.complaint.service.ComplaintService;
import com.xinqi.modules.user.user.client.UserClient;
import com.xinqi.modules.user.user.dto.rsp.UserResultDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 聊天投诉表服务层实现
 *
 * @author: yyzhenn
 * @date: 2023/04/23
 */
@Slf4j
@Validated
@Service("complaintService")
@RequiredArgsConstructor
public class ComplaintServiceImpl implements ComplaintService {

    private final ComplaintConvert complaintConvert;

    private final ComplaintManager complaintManager;

    private final ComplaintConfigManager complaintConfigManager;

    private final RemoteRongyunClient rongYunClient;

    private final ChatRemindContentClient remindContentClient;

    private final UserClient userClient;


    /**
     * 分页查询 聊天投诉表数据
     */
    @Override
    @DS("slaver")
    public PageInfo<ComplaintResultDTO> page(Param pageable, ComplaintQueryDTO query) {
        if (CollectionUtil.isEmpty(pageable.getSorts())) {
            //封装排序
            pageable.setOrderByColumn(StringUtils.EMPTY);
            pageable.setIsAsc(StringUtils.EMPTY);
            pageable.setSorts(new ArrayList<>());
            //默认排序
            pageable.getSorts().add("t.createTime,DESC");
        }
        Page<ComplaintResultDTO> page = complaintManager.findPage(Pages.page(pageable), query);
        return Pages.convert(page);
    }

    /**
     * 根据id查询 聊天投诉表数据
     */
    @Override
    public ComplaintResultDTO findById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), MessageUtils.message("complaint.id.not.blank"));
        return complaintManager.findById(id);
    }

    /**
     * 新增 聊天投诉表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insert(ComplaintCreateDTO dto) {
        ComplaintEntity entity = complaintConvert.create(dto);
        entity.setStatus(YesNoNumberEnum.NO.getCode());
        entity.setCreateBy(dto.getOperationUserId());
        entity.setCreateTime(LocalDateTime.now());
        complaintManager.save(entity);
        //新奇提醒机器人 -- 用户投诉
        List<UserResultDTO> userList = userIdToList(entity.getTouserId());
        if (CollectionUtil.isNotEmpty(userList)) {
            List<String> nicknameList = userList.stream().map(UserResultDTO::getNickname).collect(Collectors.toList());
            Map<String, Object> params = new HashMap<>();
            params.put("userName", String.join(",", nicknameList));
            String content = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_USER_COMPLAINTS_TEMPLATE, params);
            remindContentClient.insert(new ChatRemindContentCreateDTO(dto.getOperationUserId(), ChatRemindTypeEnum.USER_COMPLAINTS, content));
        }

        return entity.getId();
    }

    /**
     * 用户投诉处理
     *
     * @Title:
     * @MethodName: handling
     * [dto]
     * @Return java.lang.Boolean
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/4/25 9:00
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean handling(ComplaintHandlingDTO dto) {
        ComplaintEntity entity = complaintManager.getById(dto.getId());
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(entity), MessageUtils.message("data.does.not.exist"));
        if (Objects.equals(YesNoNumberEnum.YES.getCode(), entity.getStatus())) {
            return true;
        }
        ComplaintConfigEntity configEntity = complaintConfigManager.getById(dto.getConfigId());
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(configEntity), MessageUtils.message("complaint.configId.not.blank"));

        entity.setConfigId(dto.getConfigId());
        entity.setReply(dto.getReply());
        entity.setReminderInformation(dto.getReminderInformation());
        entity.setHandlingEmployees(dto.getOperationUserId());
        entity.setStatus(YesNoNumberEnum.YES.getCode());
        entity.setReplyTime(LocalDateTime.now());

        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();
        if (Objects.equals(ComplaintConfigDisableFeatureEnum.CHAT.getCode(), configEntity.getDisableFeature())) {
            //聊天封禁
            //remindList = chatBan(configEntity, entity);
            // TODO: 2023/8/21 融云封禁后导致融云token被封禁，无法登陆；登录时校验融云token，因此直接采用账号封禁
            remindList = accountBan(configEntity, entity);
        } else if (Objects.equals(ComplaintConfigDisableFeatureEnum.ACCOUNT.getCode(), configEntity.getDisableFeature())) {
            //账号封禁
            remindList = accountBan(configEntity, entity);
        } else if (Objects.equals(ComplaintConfigDisableFeatureEnum.INVALID_COMPLAINT.getCode(), configEntity.getDisableFeature())) {
            //投诉无效 -- 当前投诉处理完成，不对被投诉用户做处理，无新奇提醒消息发送
        }
        if (CollectionUtils.isNotEmpty(remindList)) {
            remindContentClient.batchInsert(new ChatRemindContentBatchCreateDTO(remindList));
        }

        return complaintManager.updateById(entity);
    }

    /**
     * 根据id删除 聊天投诉表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), MessageUtils.message("complaint.id.not.blank"));
        return complaintManager.removeById(id);
    }

    /**
     * 根据id删除 聊天投诉表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(ComplaintDeleteDTO dto) {
        return deleteById(dto.getId());
    }

    /**
     * 定时任务 -- 账号解封
     */
    @Override
    public void accountUnblocking() {
        log.info("定时任务 -- 账号解封");
        AccountUnblockingQueryDTO query = new AccountUnblockingQueryDTO();
        query.setBanEndTime(LocalDateTime.now());
        query.setStatus(YesNoNumberEnum.YES.getCode());
        query.setDisableFeature(Arrays.asList(ComplaintConfigDisableFeatureEnum.CHAT.getCode(), ComplaintConfigDisableFeatureEnum.ACCOUNT.getCode()));
        query.setUserStatus(UserStatusEnum.DISABLE.getCode());
        List<ComplaintEntity> list = complaintManager.selectBan(query);
        if (CollectionUtil.isEmpty(list)) {
            return;
        }
        Set<Long> userIdList = new HashSet<>();
        list.stream().forEach(item -> {
            if (StringUtils.isNotEmpty(item.getTouserId())) {
                List<String> list1 = Arrays.asList(item.getTouserId().split(","));
                for (String userId : item.getTouserId().split(",")) {
                    userIdList.add(Long.parseLong(userId));
                }
            }
        });
        List<Long> userIds = new ArrayList<>(userIdList);
        log.info("userIds => {}", userIds);
        if (CollectionUtil.isNotEmpty(userIds)) {
            userClient.accountUnblocking(userIds);
        }
    }

    private List<UserResultDTO> userIdToList(String userId) {
        List<UserResultDTO> userList = new ArrayList<>();
        if (StringUtils.isEmpty(userId)) {
            return userList;
        }
        String[] str = userId.split(",");
        List<Long> userIds = new ArrayList<>();
        for (int i = 0; i < str.length; i++) {
            userIds.add(Long.parseLong(str[i]));
        }
        userList = R.as(userClient.findList(userIds));
        return userList;
    }

    /**
     * 聊天封禁
     *
     * @param configEntity
     * @param entity
     * @return
     */
    private List<ChatRemindContentCreateDTO> chatBan(ComplaintConfigEntity configEntity, ComplaintEntity entity) {
        //新奇提醒机器人
        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();
        if (Objects.isNull(configEntity.getDisableDuration())) {
            return remindList;
        }
        LocalDateTime banEndTime = entity.getReplyTime().plusDays(configEntity.getDisableDuration());
        entity.setBanEndTime(banEndTime);
        List<UserResultDTO> userList = userIdToList(entity.getTouserId());
        if (CollectionUtil.isEmpty(userList)) {
            return remindList;
        }
        //天 -> 分钟
        Integer minute = configEntity.getDisableDuration() * 24 * 60;
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS);
        String datetime = banEndTime.format(formatter);
        //新奇提醒机器人 -- 被投诉用户
        Map<String, Object> params1 = new HashMap<>();
        params1.put("disableDuration", configEntity.getDisableDuration());
        params1.put("datetime", datetime);
        String content1 = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_USER_COMPLAINTS_HANDLING_CHAT_TEMPLATE, params1);
        List<String> nicknameList = new ArrayList<>();
        userList.forEach(item -> {
            //封禁时长，单位为分钟，最大值为 43200 分钟 -- 30天
            if (minute > 0) {
                rongYunClient.ban(item.getId().toString(), minute);
            }
            nicknameList.add(item.getNickname());
            remindList.add(new ChatRemindContentCreateDTO(item.getId(), ChatRemindTypeEnum.USER_COMPLAINTS, content1));
        });
        //新奇提醒机器人 -- 投诉用户
        Map<String, Object> params2 = new HashMap<>();
        params2.put("userName", String.join(",", nicknameList));
        String content2 = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_USER_COMPLAINTS_SUCCESS_TEMPLATE, params2);
        remindList.add(new ChatRemindContentCreateDTO(entity.getCreateBy(), ChatRemindTypeEnum.USER_COMPLAINTS, content2));
        return remindList;
    }

    /**
     * 账号封禁
     *
     * @param configEntity
     * @param entity
     * @return
     */
    private List<ChatRemindContentCreateDTO> accountBan(ComplaintConfigEntity configEntity, ComplaintEntity entity) {
        //新奇提醒机器人
        List<ChatRemindContentCreateDTO> remindList = new ArrayList<>();
        if (Objects.isNull(configEntity.getDisableDuration())) {
            return remindList;
        }
        LocalDateTime banEndTime = entity.getReplyTime().plusDays(configEntity.getDisableDuration());
        entity.setBanEndTime(banEndTime);
        List<UserResultDTO> userList = userIdToList(entity.getTouserId());
        if (CollectionUtil.isEmpty(userList)) {
            return remindList;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS);
        String datetime = banEndTime.format(formatter);
        //新奇提醒机器人 -- 被投诉用户
        Map<String, Object> params1 = new HashMap<>();
        params1.put("disableDuration", configEntity.getDisableDuration());
        params1.put("datetime", datetime);
        String content1 = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_USER_COMPLAINTS_HANDLING_ACCOUNT_TEMPLATE, params1);
        List<String> nicknameList = new ArrayList<>();
        List<Long> userIds = new ArrayList<>();
        userList.forEach(item -> {
            nicknameList.add(item.getNickname());
            userIds.add(item.getId());
            remindList.add(new ChatRemindContentCreateDTO(item.getId(), ChatRemindTypeEnum.USER_COMPLAINTS, content1));
        });
        if (CollectionUtil.isNotEmpty(userIds) && configEntity.getDisableDuration() > 0) {
            userClient.accountBan(userIds);
        }
        //新奇提醒机器人 -- 投诉用户
        Map<String, Object> params2 = new HashMap<>();
        params2.put("userName", String.join(",", nicknameList));
        String content2 = PlaceholderUtils.replaceWithMap(ChatRemindConstants.REMIND_USER_COMPLAINTS_SUCCESS_TEMPLATE, params2);
        remindList.add(new ChatRemindContentCreateDTO(entity.getCreateBy(), ChatRemindTypeEnum.USER_COMPLAINTS, content2));
        return remindList;
    }


}
